package service;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

public class ChatThread implements Runnable {
    private Socket socket;
    private String ip;
    private int port;
    private String user;
    private static HashMap<String, Socket> userSocketMap = new HashMap<>();
    private static CopyOnWriteArrayList<String> userList = new CopyOnWriteArrayList<>();
    private static HashMap<String, String> userNickMap = new HashMap<>();
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public ChatThread(Socket socket, String ip, String port) {
        this.socket = socket;
        this.ip = ip;
        this.port = Integer.parseInt(port);
        user = ip + ":" + port;
        userNickMap.put(user, user);
    }

    @Override
    public void run() {
        // 添加用户
        userSocketMap.put(user, socket);
        userList.add(user);

        try {
            OutputStream os = socket.getOutputStream();
            InputStream is = socket.getInputStream();
            String welcome = df.format(new Date()) + "已连接";
            os.write(welcome.getBytes());
            broadcastOnlineUsers();

            byte[] buffer = new byte[1024];
            while (is.read(buffer) != -1) {
                String message = new String(buffer).trim();
                if (message.startsWith("NICK|")) {
                    String newNick = message.substring(5);
                    userNickMap.put(user, newNick);
                    broadcastNickUpdate(user, newNick);
                } else if (message.contains("|")) {
                    String[] parts = message.split("\\|", 2);
                    String targetUser = parts[0];
                    String content = parts[1];
                    forwardMessage(targetUser, content);
                }
            }
        } catch (IOException e) {
            System.out.println("输入输出异常");
        } finally {
            // 用户断开连接
            userSocketMap.remove(user);
            userList.remove(user);
            userNickMap.remove(user);
            broadcastOnlineUsers();
            try {
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void broadcastOnlineUsers() {
        StringBuilder stringBuilder = new StringBuilder();
        for (String user : userList) {
            stringBuilder.append(user);
            stringBuilder.append(",");
        }
        if (stringBuilder.length() > 0) {
            stringBuilder.deleteCharAt(stringBuilder.length() - 1); // 删除最后一个逗号
        }
        String userListStr = stringBuilder.toString();

        for (Map.Entry<String, Socket> entry : userSocketMap.entrySet()) {
            try {
                OutputStream os = entry.getValue().getOutputStream();
                os.write(userListStr.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void forwardMessage(String targetUser, String content) {
        Socket targetSocket = userSocketMap.get(targetUser);
        if (targetSocket != null) {
            try {
                OutputStream os = targetSocket.getOutputStream();
                // 添加发送者的用户名信息
                String senderNick = userNickMap.get(user);
                String fullMessage = senderNick + "|" + content;
                os.write(fullMessage.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void broadcastNickUpdate(String user, String newNick) {
        String updateMessage = "NICK_UPDATE|" + user + ":" + newNick;
        for (Map.Entry<String, Socket> entry : userSocketMap.entrySet()) {
            try {
                OutputStream os = entry.getValue().getOutputStream();
                os.write(updateMessage.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}